#include "LittleClockUI.h"
#include "string.h"
#include "System.h"
#include "BATADC.h"


//定义的跨文件的全局变量
uint16_t fps = 0; //帧率
uint8_t update_flag = 0; 

//-------枚举id，唯一标识一个页面，防止有两个页面使用同一id
enum
{
    main_page_id = 0x00,
        calendar_page_id,
        clock_page_id,
        alarm_list_page_id,
            alarm1_page_id,
            alarm2_page_id,
        about_page_id,
    
    ring_page_id, //这个页面是单独游离的，只有闹钟时才会调出来
};
//--------定义页面对象
TitlePage main_page;
DigitalPage calendar_page;
DigitalPage clock_page;
ListPage alarm_list_page;
DigitalPage alarm1_page;
DigitalPage alarm2_page;
RaderPicPage about_page;
RaderPicPage ring_page; //闹钟响起时的界面(空的RaderPicPage页面，用于自己绘制)

//--------定义每个页面需要的一些参数
//部分页面内选项个数
#define MAIN_PAGE_NUM           5   
#define CALENDAR_LABEL_NUM      7
#define ALARM_LIST_PAGE_NUM     3
#define ALARM12_LABEL_NUM       3
#define ABOUT_PAGE_NUM          1   


//定义部分页面选项
//********main页面的选项
Option mian_option_array[MAIN_PAGE_NUM] = 
{///{ order,max,min,step,int_val,text,} //option的成员顺序，但对单纯title的页面来说，只有text需要赋值
    {.text = "- Calendar"},  //前两个字符是前缀，不显示，用于标识一般选项(-),二值选项(+),数值弹窗(~),确认弹窗($)
    {.text = "- Clock"},
    {.text = "- Alarm"},
    {.text = "~ BATLevel", .item_max = 100, .item_min = 0, .step = 0,.val = 50,}, 
    //数值弹窗电压显示(step = 0，则为只读，无法使用按键编辑(其实就是使操作+-0，无效))
    {.text = "- Aoubt"},
};
//main页面的图标
Icon main_icon_array[MAIN_PAGE_NUM] = 
{
    [0] = {0xF0,0xF8,0x38,0x38,0x38,0x38,0x7F,0xFF,0x7F,0x38,0x38,0x38,0x38,0x38,0x38,0x38,
            0x38,0x38,0x38,0x38,0x38,0x7F,0xFF,0xFF,0x38,0x38,0x38,0x38,0xF8,0xF0,0xFF,0xFF,
            0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x8E,0x8E,0xCE,0xCE,0x0E,0x0E,
            0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0xFF,0xFF,0xFF,0xFF,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x1F,0x3F,0x38,0x38,0x38,0x38,
            0x38,0x38,0x38,0x38,0x38,0x39,0x3B,0x3B,0x39,0x39,0x3B,0x3B,0x39,0x38,0x38,0x38,
            0x38,0x38,0x38,0x38,0x38,0x38,0x3F,0x1F}, //Canlendar 
    [1] = {0x00,0x00,0xC0,0xE0,0xF0,0x38,0x1C,0x1C,0x0E,0x06,0x07,0x07,0x07,0x03,0xE3,0xE3,
            0x03,0x07,0x07,0x07,0x06,0x0E,0x1C,0x1C,0x38,0xF0,0xE0,0xC0,0x00,0x00,0xFC,0xFF,
            0x1F,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x80,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x1F,0xFF,0xFC,0x0F,0x3F,0xFE,0xE0,
            0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x07,
            0x07,0x07,0x07,0x06,0x0E,0xCE,0xE2,0xFE,0x3F,0x0F,0x00,0x00,0x00,0x01,0x03,0x07,
            0x0E,0x0E,0x1C,0x18,0x38,0x38,0x38,0x30,0x30,0x30,0x30,0x38,0x38,0x38,0x18,0x1C,
            0x0E,0x0E,0x07,0x03,0x01,0x00,0x00,0x00}, //clock
    [2] = {0xF0,0xF8,0x9C,0xCE,0xEE,0x76,0xBE,0xDC,0xEC,0x60,0x70,0x30,0x38,0x38,0xF8,0xF8,
            0x38,0x38,0x30,0x30,0x70,0xEC,0xDC,0xFE,0xF6,0xEE,0xCE,0x9C,0xFC,0xF0,0x01,0x03,
            0xE7,0xFB,0xFF,0x0F,0x03,0x01,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFF,0xFF,0x00,0x00,
            0x00,0x00,0x00,0x00,0x01,0x03,0x0F,0xFE,0xFD,0xE7,0x03,0x01,0x00,0x00,0x01,0x1F,
            0x7F,0xF8,0xE0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x80,0xC0,0xF0,0x7F,0x1F,0x03,0x00,0x00,0x00,0x00,0x00,0x0C,0x1E,0x0F,
            0x07,0x03,0x07,0x07,0x0E,0x0E,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0E,0x0E,0x07,0x07,
            0x03,0x03,0x07,0x0E,0x1C,0x08,0x00,0x00}, //alarm
    [3] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x60,
            0x30,0x18,0x18,0x10,0x30,0x70,0xD8,0x98,0x18,0x30,0xE0,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x80,0xC0,0xE0,0x30,0x18,0x4C,0x26,0x13,0x03,0x01,0x00,0x00,0x00,0x00,
            0x0A,0x04,0x0A,0x00,0x00,0x81,0xC2,0x6F,0x39,0x00,0x00,0x00,0x00,0x00,0x1E,0x33,
            0x41,0x81,0x00,0x10,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x60,0x30,0x18,
            0x0C,0x06,0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x01,0x02,0x06,0x0C,0x08,0x08,0x0C,0x06,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //Bat level
    [4] = {0x00,0x00,0xC0,0xE0,0xF0,0x38,0x1C,0x1C,0x0E,0x06,0x07,0x07,0x07,0x03,0x03,0x03,
            0x03,0x03,0x07,0x07,0x06,0x0E,0x1C,0x1C,0x38,0xF0,0xE0,0xC0,0x00,0x00,0xFC,0xFF,
            0x1F,0x01,0x00,0xC0,0xE0,0xE0,0xC0,0x00,0x00,0x00,0x00,0xC0,0xE0,0xE0,0xC0,0x00,
            0x00,0x00,0x00,0xC0,0xE0,0xE0,0xC0,0x00,0x01,0x1F,0xFF,0xF8,0x0F,0x3F,0xFE,0xE0,
            0xC0,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00,
            0x00,0x00,0x01,0x01,0x00,0xC0,0xF0,0xFE,0x3F,0x0F,0x00,0x00,0x00,0x01,0x03,0x07,
            0x0E,0x0E,0x1C,0x18,0x38,0x38,0x38,0x30,0x30,0x30,0x30,0x38,0x38,0x38,0x18,0x1C,
            0x0E,0x0E,0x07,0x03,0x01,0x00,0x00,0x00}, //more
};

//Calendar 页面的选项
Option calendar_option_array[3] = 
{///{ order,max,min,step,int_val,text,}
   [Digital_Pos_IndexLeft] = { .item_max = 99, .item_min = 0, .step = 1, .text = "Year"},  
   [Digital_Pos_IndexMid] = { .item_max = 12, .item_min = 1, .step = 1, .text = "Month"},  
   [Digital_Pos_IndexRight] = { .item_max = 31, .item_min = 1, .step = 1, .text = "day"},  
};
//标签数组
String week_str[CALENDAR_LABEL_NUM] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};

//Clock页面选项
Option clock_option_array[3]=
{
    [Digital_Pos_IndexLeft] = { .item_max = 23, .item_min = 0, .step = 1, .text = "Hour"},
    [Digital_Pos_IndexMid] = { .item_max = 59, .item_min = 0, .step = 1, .text = "Minute"},
    [Digital_Pos_IndexRight] = { .item_max = 59, .item_min = 0, .step = 1, .text = "Second"},
};

//alarm页面选项
Option alarm_list_option_array[3]=
{
    {.text = "  alarm list"},
    {.text = "+ Alarm1", .val = 0,}, //为二值选项，单选项值由Alarm12页面控制(读全局update_flag中enable_msk位可以设置)
    {.text = "+ Alarm2", .val = 0,}, //默认值为0，close
};

//alarm1页面选项
Option alarm1_option_array[3]=
{
    [Digital_Pos_IndexLeft] = { .item_max = 23, .item_min = 0, .step = 1, .text = "Hour"},
    [Digital_Pos_IndexMid] = { .item_max = 59, .item_min = 0, .step = 1, .text = "Minute"},
    [Digital_Pos_IndexRight] = { .item_max = 59, .item_min = 0, .step = 1, .text = "Second"},
};
Option alarm2_option_array[3]=
{
    [Digital_Pos_IndexLeft] = { .item_max = 23, .item_min = 0, .step = 1, .text = "Hour"},
    [Digital_Pos_IndexMid] = { .item_max = 59, .item_min = 0, .step = 1, .text = "Minute"},
    [Digital_Pos_IndexRight] = { .item_max = 59, .item_min = 0, .step = 0, .text = "Second"},
    //DS3231只有两个闹钟，且闹钟2的秒无效，所以alarm2的step为0,为不可编辑模式
    //(因为air001的内存不够，也不想做软件闹钟了)
};
String alarm12_label_array[3] = { "Close", "Open", "Delete"};




//About页面
const uint8_t QRCode[] = {
      0xFF,0xFF,0xFF,0x07,0x07,0xE7,0x27,0x27,0x27,0x27,0x27,0x27,0xE7,0x07,0x07,0xFF,
      0xFF,0xDF,0x1F,0x1F,0x27,0x27,0x27,0x27,0xFF,0xC7,0xC7,0x27,0x27,0x1F,0x1F,0xFF,
      0xFF,0xFF,0x07,0x07,0xE7,0x27,0x27,0x27,0x27,0x27,0x27,0xE7,0x07,0x07,0xFF,0xFF,
      0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x80,0x9F,0x90,0x90,0x90,0x90,0x90,0x90,0x9F,0x80,
      0x80,0xFF,0xFF,0x93,0xF0,0xF0,0x90,0x90,0xF3,0xF3,0x90,0x6F,0x6F,0x9F,0x9F,0xEC,
      0xEC,0x0F,0xFF,0xFF,0x80,0x80,0x9F,0x90,0x90,0x90,0x90,0x90,0x90,0x9F,0x80,0x80,
      0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0x01,0x3F,0x31,0x31,0x3F,0x3F,0xF1,0xF1,
      0x3F,0xCD,0xCD,0xC3,0xC3,0xCF,0x0F,0x0F,0xFF,0xFF,0x03,0x03,0x3F,0x00,0x00,0xCF,
      0xCF,0xFD,0xFD,0x0C,0x3F,0x3F,0x03,0x03,0x0F,0xCD,0xCD,0xFF,0xFF,0xCF,0xCF,0x0D,
      0xC3,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x66,0x66,0x9E,0x86,0x86,0x9F,0x9F,
      0x07,0x07,0x80,0x66,0x66,0x66,0x66,0xFE,0x86,0x86,0xE0,0xE0,0x98,0x98,0x7F,0x87,
      0x87,0xE7,0xE7,0xFE,0xFE,0x78,0x1F,0x1F,0x60,0x60,0x66,0x1F,0x1F,0x78,0x78,0xE7,
      0xE7,0x86,0xE0,0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0x03,0xF3,0x13,0x13,
      0x13,0x13,0x13,0x13,0xF3,0x03,0x03,0xFF,0xFF,0x9C,0x00,0x00,0x73,0x73,0x10,0x10,
      0xE0,0xEF,0xEF,0x80,0x80,0x70,0x70,0x00,0x1F,0x1F,0x93,0x93,0x1F,0x00,0x00,0x00,
      0x00,0x7F,0x7F,0x80,0x80,0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,0xC0,0xCF,
      0xC8,0xC8,0xC8,0xC8,0xC8,0xC8,0xCF,0xC0,0xC0,0xFF,0xFF,0xC9,0xC0,0xC0,0xFE,0xFE,
      0xF6,0xF6,0xCF,0xF9,0xF9,0xFF,0xFF,0xF0,0xF0,0xC6,0xC8,0xC8,0xFF,0xFF,0xCE,0xF0,
      0xF0,0xF6,0xF6,0xFE,0xFE,0xC7,0xC9,0xC9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
      0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
      0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
      0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
}; //Qrcode

RaderPic qrcode_raderpic[ABOUT_PAGE_NUM] = 
{
    {.pic = QRCode, .start_x = 7, .start_y = 7, .w = 50, .h = 50, .rd = RD_RIGHT_DOWN},
};

//--------定义每个页面的回调函数
void MainPage_CallBack(uint8_t self_page_id,Option* select_item)
{
    switch (select_item->order)
    {
        case 0: OLED_UIJumpToPage(self_page_id,&calendar_page); break;
        case 1: OLED_UIJumpToPage(self_page_id,&clock_page);  break;
        case 2: OLED_UIJumpToPage(self_page_id,&alarm_list_page); break;
        case 3:  //更新电量
                select_item->val = BATADC_Read();
            break;
        case 4: OLED_UIJumpToPage(self_page_id,&about_page); break;
        default: break;
    }
}

void CalendarPage_CallBack(uint8_t self_page_id,Option* select_item)
{
    uint8_t month_days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
    switch (select_item->order)
    {
        case Digital_Pos_Complete : //全部数据设置完成后，也会检测一次数据
            SET_FLAG(update_flag,DATE_UPDATE_MSK); //同时会通知main函数设置rtc芯片
        case Digital_Pos_IndexRight: //更正日期数据 
            if( calendar_page.option_array[Digital_Pos_IndexRight].val >  //大于每个月的最大月数，更正日期
                month_days[calendar_page.option_array[Digital_Pos_IndexMid].val -1])
               OLED_DigitalPage_UpdateDigitalNumAnimation(&calendar_page,
                 calendar_page.option_array[Digital_Pos_IndexLeft].val,
                 calendar_page.option_array[Digital_Pos_IndexMid].val,
                 month_days[calendar_page.option_array[Digital_Pos_IndexMid].val -1], Digital_Direct_Decrease);
            break;
        default:break;
    }

}

void ClockPage_CallBack(uint8_t self_page_id,Option* select_item)
{
    if(select_item->order == Digital_Pos_Complete) //时间设置完成
        SET_FLAG(update_flag,TIME_UPDATE_MSK); //通知主函数更新时间
}


void AlarmList_CallBack(uint8_t self_page_id,Option* select_item)
{
    switch (select_item->order)
    {
        // case 0: 
            // OLED_UIJumpToPage(self_page_id, &ring_page); //只是作为绘制页面的跳转测试 
            // break;
        case 1: 
            OLED_UIJumpToPage(self_page_id, &alarm1_page); 
            //设置其标签
            alarm1_page.select_label_index = (!!FLAG_IS_SET(update_flag, ALARM1_ENABLE_MSK)); //将数值变量转为逻辑
            break;
        case 2: 
            OLED_UIJumpToPage(self_page_id, &alarm2_page); 
            alarm2_page.select_label_index = (!!FLAG_IS_SET(update_flag, ALARM2_ENABLE_MSK)); //将数值变量转为逻辑
            break;
        default :break;
    }
} 

void Alarm12_CallBack(uint8_t self_page_id,Option* select_item)
{
    uint8_t update_msk = 0;
    uint8_t enable_msk = 0;
    if(self_page_id == alarm1_page_id){update_msk = ALARM1_UPDATE_MSK;enable_msk = ALARM1_ENABLE_MSK;}
    else if(self_page_id == alarm2_page_id){update_msk = ALARM2_UPDATE_MSK;enable_msk = ALARM2_ENABLE_MSK;}
    switch (select_item->order)
    {
        case Digital_Pos_Complete: //编辑完成
            SET_FLAG(update_flag, update_msk);
            break;
        case Digital_Pos_IndexLabel: //click标签时
            if(strcmp(select_item->text, alarm12_label_array[0]) == 0) //close
                CLEAR_FLAG(update_flag,enable_msk);   
            else if(strcmp(select_item->text, alarm12_label_array[1]) == 0) //open
                SET_FLAG(update_flag,enable_msk);   
            else if(strcmp(select_item->text, alarm12_label_array[2]) == 0) //Delete
            {
                CLEAR_FLAG(update_flag,enable_msk);  //闹钟标志位关闭
                if(self_page_id == alarm1_page_id)
                    OLED_DigitalPage_UpdateDigitalNumAnimation(&alarm1_page, 0,0,0,Digital_Direct_Decrease);
                else if(self_page_id == alarm2_page_id)
                    OLED_DigitalPage_UpdateDigitalNumAnimation(&alarm2_page, 0,0,0,Digital_Direct_Decrease);
            }
        default:
            break;
    }
}


void About_CallBack(uint8_t self_page_id,Option* select_item)
{
    uint8_t buff[10] = {0};
    sprintf((char*)buff, "fps:%d",fps);
    if(select_item->order == ABOUT_PAGE_NUM) //图像绘制完成后
    {
        OLED_WinDrawStr(&w_all, 64, 7, 16, buff);
        OLED_WinDrawStr(&w_all, 64, 24, 16, "Scan");
        OLED_WinDrawStr(&w_all, 64, 40, 16, "QrCode");
    }
}

void Ring_CallBack(uint8_t self_page_id,Option* select_item)
{
    static float x = 2; 
    static float x_trg = 12;
    static uint8_t color = 1;
    OLED_Animation(&x, &x_trg, 200);
    OLED_WinDrawBMP(&w_all, 15, 15 , 30, 30 , main_icon_array[2], color); // 实色绘制闹钟图标
    OLED_SetPointColor(2); //反色绘制
    int16_t len = 62-2*x;
    OLED_WinDrawRBox(&w_all, x, x, len, len,2);
    OLED_SetPointColor(1); //恢复正常颜色
    if(x == x_trg)
    {
        if(x_trg == 12){x_trg = 2;color =! color;}
        else if(x_trg == 2){x_trg = 12;color =! color;}
    }
    if(FLAG_IS_SET(update_flag, ALARM1_RING_MSK))
        OLED_WinDrawStr(&w_all, 60, 8, 16, "Alarm1");
    else if((FLAG_IS_SET(update_flag, ALARM2_RING_MSK)))
        OLED_WinDrawStr(&w_all, 60, 8, 16, "Alarm2");
    OLED_WinDrawStr(&w_all, 60, 34, 8, "Press Any");
    OLED_WinDrawStr(&w_all, 60, 44, 8, "Key to exit!");
}


//-------------一些需要用的内部函数

//--------------给主函数调用的接口函数

void LittleClockUI_Init(void)
{
    OLED_Init();  //硬件的初始化
    LL_mDelay(100);
    OLED_ClearBuff(); //清空缓存
    OLED_RefreshBuff(); //刷新屏幕(清空屏幕)
    OLED_SetPointColor(1); //设置绘制颜色
    OLED_UiInit();  //必要的ui参数初始化
    OLED_TitlePageInit(&main_page, main_page_id, MAIN_PAGE_NUM, mian_option_array, main_icon_array, MainPage_CallBack);
    OLED_DigitalPageInit(&calendar_page, calendar_page_id, calendar_option_array, CALENDAR_LABEL_NUM, week_str, '-', 0, 100, CalendarPage_CallBack);
    OLED_DigitalPageInit(&clock_page, clock_page_id, clock_option_array, CALENDAR_LABEL_NUM, week_str, ':', 50, 100, ClockPage_CallBack); //时钟页面的标签也显示周
    OLED_ListPageInit(&alarm_list_page, alarm_list_page_id, ALARM_LIST_PAGE_NUM, alarm_list_option_array, AlarmList_CallBack);
    OLED_DigitalPageInit(&alarm1_page, alarm1_page_id, alarm1_option_array, ALARM12_LABEL_NUM, alarm12_label_array, ':', 50, 100, Alarm12_CallBack); 
    OLED_DigitalPageInit(&alarm2_page, alarm2_page_id, alarm2_option_array, ALARM12_LABEL_NUM, alarm12_label_array, ':', 50, 100, Alarm12_CallBack); 
    OLED_RaderPicPageInit(&about_page, about_page_id, ABOUT_PAGE_NUM, qrcode_raderpic, Rader_Pic_Mode_Hold, About_CallBack);
    OLED_RaderPicPageInit(&ring_page, ring_page_id, 0, NULL, Rader_Pic_Mode_Hold, Ring_CallBack); //相当于一个空的页面可以自由绘制

}


void LittleClockUI_Proc(void)
{
    OLED_UIProc();
    //由updataflag接管 alarmlist中两个选框的选中与否
    if(FLAG_IS_SET(update_flag,ALARM1_ENABLE_MSK))alarm_list_option_array[1].val = 1;
    else alarm_list_option_array[1].val = 0;
    if(FLAG_IS_SET(update_flag,ALARM2_ENABLE_MSK))alarm_list_option_array[2].val = 1;
    else alarm_list_option_array[2].val = 0;
}
